package ch.haclyon.driveimageview;


import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.render.Path;
import ohos.agp.utils.Color;
import ohos.agp.utils.Rect;
import ohos.agp.utils.TextAlignment;
import ohos.agp.window.service.Display;
import ohos.agp.window.service.DisplayManager;
import ohos.app.Context;

import java.util.HashMap;
import java.util.Map;

public class DriveImageViewLayout extends Component implements Component.DrawTask{
    /**
     * integerMap
     */
    private static final Map<String, Integer> INTEGER_MAP = new HashMap<>();

    /**
     * canvasWidth
     */
    private static int canvasWidth = 0;

    /**
     * canvasHeight
     */
    private static int canvasHeight = 0;

    /**
     * backgroundPaint
     */
    private Paint backgroundPaint;

    /**
     * outlinePaint
     */
    private Paint outlinePaint;

    /**
     * textPaint
     */
    private Paint textPaint;

    /**
     * customHeight
     */
    private float customHeight;

    /**
     * customFolderSpacing
     */
    private float customFolderSpacing;

    /**
     * folderCorner
     */
    private float folderCorner = 14f;

    /**
     * imageViewHeight
     */
    private float imageViewHeight;

    /**
     * imageViewWidth
     */
    private float imageViewWidth;

    /**
     * folderText
     */
    private String folderText;

    /**
     * mainText
     */
    private String mainText;

    /**
     * backgroundColour
     */
    private String backgroundColour = "#094ab2";

    /**
     * divideColour
     */
    private String divideColour = "#FFFFFF";

    /**
     * textColour
     */
    private String textColour = "#FFFFFF";

    /**
     * alphaValue
     */
    private float alphaValue = 1;

    /**
     * context
     */
    private Context context;

    /**
     * folderRect
     */
    private Rect folderRect;

    /**
     * mainRect
     */
    private Rect mainRect;

    /**
     * paint
     */
    private final Paint paint = new Paint();

    /**
     * DriveImageViewLayout
     *
     * @param context context
     */
    public DriveImageViewLayout(Context context) {
        super(context);
        initializePaints(context);
    }

    /**
     * DriveImageViewLayout
     *
     * @param context context
     * @param attrs attrs
     */
    public DriveImageViewLayout(Context context, AttrSet attrs) {
        super(context, attrs);
        initializePaints(context);
    }

    /**
     * DriveImageViewLayout
     *
     * @param context context
     * @param attrs attrs
     * @param defStyleAttr defStyleAttr
     */
    public DriveImageViewLayout(Context context, AttrSet attrs, String defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initializePaints(context);
    }

    /**
     * initializePaints
     *
     * @param context context
     */
    private void initializePaints(Context context) {
        this.context = context;
        backgroundPaint = new Paint();
        backgroundPaint.setColor(new Color(Color.getIntColor(backgroundColour)));
        backgroundPaint.setStrokeWidth(convertDpToPx(10, context));
        backgroundPaint.setAntiAlias(true);
        backgroundPaint.setStyle(Paint.Style.FILL_STYLE);
        outlinePaint = new Paint();
        outlinePaint.setColor(new Color(Color.getIntColor(divideColour)));
        outlinePaint.setStrokeWidth(convertDpToPx(3, context));
        outlinePaint.setAntiAlias(true);
        outlinePaint.setStyle(Paint.Style.STROKE_STYLE);
        textPaint = new Paint();
        textPaint.setColor(new Color(Color.getIntColor(textColour)));
        textPaint.setAntiAlias(true);
        textPaint.setTextSize(convertDpToPx(30, context));
        textPaint.setStyle(Paint.Style.FILL_STYLE);
        Paint debugPaint = new Paint();
        String debugColour = "#FF0000";
        debugPaint.setColor(new Color(Color.getIntColor(debugColour)));
        debugPaint.setAntiAlias(true);
        debugPaint.setStyle(Paint.Style.STROKE_STYLE);
        folderCorner = convertDpToPx(folderCorner, context);
        getWritableFolderRect(canvasWidth);
        // 添加绘制任务
        addDrawTask(this);
    }


    @Override
    public void onDraw(Component component, Canvas canvas) {
        if (canvasWidth == 0) {
            canvasWidth = component.getWidth();
        }
        if (canvasHeight == 0) {
            canvasHeight = component.getHeight();
        }

        if (imageViewHeight == 0.0) {
            return;
        }

        if (customFolderSpacing == 0.0) {
            this.customFolderSpacing = Float.parseFloat(
                    String.valueOf(imageViewWidth - (imageViewWidth / ((1 + Math.sqrt(5)) / 2))));
        }

        if (customHeight == 0.0) {
            this.customHeight = Float.parseFloat(
                    String.valueOf(imageViewHeight - (imageViewHeight / ((1 + Math.sqrt(5)) / 2))));
        }
        canvas.drawRect(0, imageViewHeight - customHeight, canvasWidth, canvasHeight, backgroundPaint);
        canvas.drawPath(getFolderPath(), backgroundPaint);
        canvas.drawPath(getDividerPath(), outlinePaint);
        if (folderText != null && folderText.length() > 0) {
            getWritableFolderRect(canvasWidth);
            textPaint.setTextSize(determineMaxTextSize(folderText, folderRect));
            canvas.drawText(textPaint,folderText, folderRect.left, folderRect.bottom);
        }
        if (mainText != null && mainText.length() > 0) {
            getWritableMainRect(canvasWidth, canvasHeight);
            textPaint.setTextSize(determineMaxTextSize(mainText, mainRect));
            textPaint.setTextAlign(TextAlignment.LEFT);

            int spacing = (int) (((mainRect.bottom - mainRect.top) / 2) -
                    ((textPaint.descent() + textPaint.ascent()) / 2));
            canvas.drawText(textPaint,
                    mainText,
                    mainRect.left,
                    mainRect.top + spacing);
        }
        setAlpha(alphaValue);
    }

    /**
     * getWritableFolderRect
     *
     * @param cw cw
     */
    private void getWritableFolderRect(int cw) {
        if (cw != 0) {
            Rect rect = new Rect();
            rect.left = (int) (imageViewWidth - customFolderSpacing + (folderCorner + 8));
            rect.top = (int) (imageViewHeight - customHeight - (folderCorner - 8));
            rect.right = cw - 16;
            rect.bottom = (int) (imageViewHeight - customHeight);
            folderRect = rect;
        }
    }

    /**
     * getWritableMainRect
     *
     * @param cw cw
     * @param ch ch
     */
    private void getWritableMainRect(int cw, int ch) {
        if (cw != 0 && ch != 0 && imageViewHeight != 0) {
            mainRect = new Rect(convertDpToPx(8, context),
                    (int) (imageViewHeight - customHeight + convertDpToPx(8, context)),
                    cw - convertDpToPx(8, context),
                    ch - convertDpToPx(8, context));
        }
    }

    /**
     * getDividerPath
     *
     * @return Path
     */
    private Path getDividerPath() {
        Path path = new Path();
        path.moveTo(0, imageViewHeight - customHeight);
        path.lineTo(imageViewWidth - customFolderSpacing, imageViewHeight - customHeight);
        path.lineTo(imageViewWidth - customFolderSpacing + folderCorner,
                imageViewHeight - customHeight - folderCorner);
        path.lineTo(canvasWidth, imageViewHeight - customHeight - folderCorner);
        return path;
    }

    /**
     * getFolderPath
     *
     * @return Path
     */
    private Path getFolderPath() {
        Path path = new Path();
        path.moveTo(imageViewWidth - customFolderSpacing, imageViewHeight - customHeight);
        path.lineTo(imageViewWidth - customFolderSpacing + folderCorner,
                imageViewHeight - customHeight - folderCorner);
        path.lineTo(canvasWidth, imageViewHeight - customHeight - folderCorner);
        path.lineTo(canvasWidth, imageViewHeight - customHeight);
        path.close();
        return path;
    }

    /**
     * setFolderText
     *
     * @param folderText folderText
     */
    public void setFolderText(String folderText) {
        this.folderText = folderText;
        this.invalidate();
    }

    /**
     * setMainText
     *
     * @param mainText mainText
     */
    public void setMainText(String mainText) {
        this.mainText = mainText;
        this.invalidate();
    }

    /**
     * determineMaxTextSize
     *
     * @param str str
     * @param rect rect
     * @return int
     */
    private int determineMaxTextSize(String str, Rect rect) {
        int size = 0;
        boolean b1, c1;
        if (!INTEGER_MAP.containsKey(str)) {
            do {
                paint.setTextSize(++size);
                Rect rec = paint.getTextBounds(str);
                b1 = (rect.right - rect.left) > (rec.right - rec.left);
                c1 = (rect.bottom - rect.top) > (rec.bottom - rec.top);
            }
            while (b1 && c1);
            INTEGER_MAP.put(str, size - 1);
        }
        return INTEGER_MAP.get(str);
    }

    /**
     * getBackgroundColour
     *
     * @return String
     */
    public String getBackgroundColour() {
        return backgroundColour;
    }

    /**
     * setBackgroundColour
     *
     * @param backgroundColour backgroundColour
     */
    public void setBackgroundColour(String backgroundColour) {
        this.backgroundColour = backgroundColour;
        backgroundPaint.setColor(new Color(Color.getIntColor(backgroundColour)));
        this.invalidate();
    }

    /**
     * getDivideColour
     *
     * @return String
     */
    public String getDivideColour() {
        return divideColour;
    }

    /**
     * setDivideColour
     *
     * @param divideColour divideColour
     */
    public void setDivideColour(String divideColour) {
        this.divideColour = divideColour;
        this.invalidate();
    }

    /**
     * getTextColour
     *
     * @return String
     */
    public String getTextColour() {
        return textColour;
    }

    /**
     * setTextColour
     *
     * @param textColour textColour
     */
    public void setTextColour(String textColour) {
        this.textColour = textColour;
        this.invalidate();
    }

    /**
     * getAlphaValue
     *
     * @return float
     */
    public float getAlphaValue() {
        return alphaValue;
    }

    /**
     * setAlphaValue
     *
     * @param alphaValue alphaValue
     */
    public void setAlphaValue(float alphaValue) {
        this.alphaValue = alphaValue;
        this.invalidate();
    }

    /**
     * getCustomHeight
     *
     * @return float
     */
    public float getCustomHeight() {
        return customHeight;
    }

    /**
     * setCustomHeight
     *
     * @param customHeight customHeight
     */
    public void setCustomHeight(float customHeight) {
        this.customHeight = convertDpToPx(customHeight, getContext());
        INTEGER_MAP.remove(mainText);
        this.invalidate();
    }

    /**
     * getCustomFolderSpacing
     *
     * @return float
     */
    public float getCustomFolderSpacing() {
        return customFolderSpacing;
    }

    /**
     * setCustomFolderSpacing
     *
     * @param customFolderSpacing customFolderSpacing
     */
    public void setCustomFolderSpacing(float customFolderSpacing) {
        this.customFolderSpacing = convertDpToPx(customFolderSpacing, getContext());
        this.invalidate();
    }

    /**
     * getImageViewHeight
     *
     * @return float
     */
    public float getImageViewHeight() {
        return imageViewHeight;
    }

    /**
     * setImageViewHeight
     *
     * @param imageViewHeight imageViewHeight
     */
    public void setImageViewHeight(float imageViewHeight) {
        this.imageViewHeight = imageViewHeight;
        this.invalidate();
    }

    /**
     * getImageViewWidth
     *
     * @return float
     */
    public float getImageViewWidth() {
        return imageViewWidth;
    }

    /**
     * setImageViewWidth
     *
     * @param imageViewWidth imageViewWidth
     */
    public void setImageViewWidth(float imageViewWidth) {
        this.imageViewWidth = imageViewWidth;
        this.invalidate();
    }

    /**
     * convertDpToPx
     *
     * @param dp dp
     * @param context context
     * @return int
     */
    public static int convertDpToPx(float dp, Context context) {
        Display display = DisplayManager.getInstance().getDefaultDisplay(context).get();
        float dpi = display.getAttributes().densityPixels;
        return (int) (dp * dpi + 0.5 * (dp >= 0 ? 1 : -1));
    }

    /**
     * getFolderCorner
     *
     * @return float
     */
    public float getFolderCorner() {
        return folderCorner;
    }

    /**
     * setFolderCorner
     *
     * @param folderCorner folderCorner
     */
    public void setFolderCorner(float folderCorner) {
        this.folderCorner = convertDpToPx(folderCorner, getContext());
        INTEGER_MAP.remove(folderText);
        this.invalidate();
    }
}
